/*
 * Project: push-center-service-impl
 * 
 * File Created at 2014-10-9
 * 
 * Copyright 2012 Greenline.com Corporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Greenline Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Greenline.com.
 */
package com.greenline.push.service.core.send;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.util.CollectionUtils;

import com.greenline.gateway.base.BaseParamPO;
import com.greenline.gateway.base.ResponseCode;
import com.greenline.gateway.base.ResponseDTO;
import com.greenline.gateway.service.qq.QQTemplateMsgService;
import com.greenline.gateway.service.qq.po.QQTemplateMsgPO;
import com.greenline.push.core.enums.Channels;
import com.greenline.push.core.enums.MsgSendType;
import com.greenline.push.core.enums.Tasks;
import com.greenline.push.service.core.exception.ChannelSendException;
import com.greenline.push.service.core.item.AppPacket;
import com.greenline.push.service.core.item.Packet;
import com.greenline.push.service.core.send.base.AbstractSender;
import com.greenline.push.service.core.send.base.AppPacketHandler;
import com.greenline.push.service.core.tmpl.AppChannelCache;
import com.greenline.push.service.core.tmpl.GroupAppCache;
import com.greenline.push.service.core.user.AppUserInfo;
import com.greenline.push.service.core.utils.Constants;

/**
 * QQSender
 * 
 * @author zhaoli
 * @date 2014-10-9
 * @version V1.0
 */
public class QQSender extends AbstractSender {
    @Resource
    private AppChannelCache appChannelCache;
    @Resource
    private GroupAppCache groupAppCache;
    @Resource
    private AppPacketHandler packetHandler;
    @Resource
    private QQTemplateMsgService qqTemplateMsgService;

    Logger log = Constants.LOG_PROCESS;

    @Override
    public Channels supportChannel() {
        return Channels.qq;
    }

    @Override
    protected boolean doSend(Packet packet) {
        //
        AppPacket appPacket = (AppPacket) packet;
        // log
        log.info(String.format(
                "{QQSender收到数据}:准备发送***domainId:[%s].tempId:[%s].type:[%s],extparam-context:[%s-%s],source:[%s],retryId:[%s],thread:[%s]",
                appPacket.getDomainId(), appPacket.getTemplateId(), appPacket.getType(), appPacket.getExtParam(), appPacket.getContext(),
                appPacket.getSource(), appPacket.getDbRetryId(), Thread.currentThread().getName()));

        ResponseDTO<Boolean> result = null;
        try {
            // 模版发送
            if (MsgSendType.POINT.getType() == appPacket.getType()) {
                result = this.sendPoint(appPacket);
            } else if (MsgSendType.UPLOAD.getType() == appPacket.getType() || MsgSendType.CONDITIONS.getType() == appPacket.getType()
                    || MsgSendType.DOMAIN.getType() == appPacket.getType()) {
                // upload 或者 condition 类型 可以调用第三方按组发送
                this.sendList(appPacket);
            }
        } catch (Exception e) {
            result = new ResponseDTO<Boolean>();
            result.setResult(ResponseCode.ERROR, e.getMessage());
            packetHandler.afterSendOperation(appPacket, false);
            log.error(String.format("{QQSender发送异常}接受者[%s].模板id:[%s],retryId:[%s].异常信息:[%s]", packet.getRecvUserId(),
                    packet.getTemplateId(), appPacket.getDbRetryId(), e.getMessage()));
        }
        return true;
    }

    private void sendList(AppPacket appPacket) {
        String methodName = "{qqSender.sendList}";
        Long retryId = appPacket.getDbRetryId();
        String appId = appPacket.getAppId();

        List<String> sResult = getUserIdsByRetryId(retryId);
        if (sResult == null) {
            log.error(String.format("%s发送失败,apppacket下没有取到用户.retryId:[%s],context:[%s]", methodName, retryId, appPacket.getContext()));
            // delete directly
            packetHandler.afterSendOperation(appPacket, false, true);
            return;
        }
        log.debug(String.format("%s批量发送qq消息.uidlist:[%s].contenxt:[%s]", methodName, sResult.toString(), appPacket.getContext()));
        // convert to p2p
        for (String userId : sResult) {
            AppUserInfo userInfo = getAppUser(userId, appId);
            if (null == userInfo)
                continue;
            appPacket.setRecvUserId(Long.valueOf(userId));
            appPacket.setDeviceToken(userInfo.getDeviceToken());
            try {
                sendPoint(appPacket);
            } catch (ChannelSendException e) {
                e.printStackTrace();
                packetHandler.afterSendOperation(appPacket, false);
            }
        }
        // getAppUser(userId, appId)
    }

    /**
     * 发送点对点消息
     * 
     * @param appPacket
     * @return
     * @throws ChannelSendException
     */
    private ResponseDTO<Boolean> sendPoint(AppPacket appPacket) throws ChannelSendException {
        String methodName = "{qqSender.sendPoint}";
        String extAppId = appChannelCache.getExtAppId(appPacket.getAppChannelId());
        if (extAppId == null) {
            log.error(String.format("%s未找到extAppid.接收人:[%s],消息:[%s],retryId:[%s]", methodName, appPacket.getDeviceToken(),
                    appPacket.getParam(), appPacket.getDbRetryId()));
            // delete
            packetHandler.afterSendOperation(appPacket, false, true);
            throw new ChannelSendException("应用：" + appPacket.getAppId() + "不存在。");
        }
        BaseParamPO<QQTemplateMsgPO> param = new BaseParamPO<QQTemplateMsgPO>();
        QQTemplateMsgPO po = new QQTemplateMsgPO();
        po.setTemplate_id(appPacket.getExtTemplId());
        po.setTouser(appPacket.getDeviceToken());
        if (!CollectionUtils.isEmpty(appPacket.getExtParam())) {
            Map<String, String> param_map = new HashMap<String, String>();
            param_map.putAll(appPacket.getExtParam());
            po.setParam(param_map);
        }
        param.setParam(po);
        param.setAppId(extAppId);
        ResponseDTO<Boolean> result = null;
        try {
            log.debug(String.format("%s.调用点对点发送 .appId:[%s],extappId:[%s],content:[%s],token:[%s],retryId:[%s]", methodName,
                    appPacket.getAppId(), extAppId, appPacket.getParam(), appPacket.getDeviceToken(), appPacket.getDbRetryId()));

            result = qqTemplateMsgService.sendTemplateMsg(param);
        } catch (Exception e) {
            e.printStackTrace();
            packetHandler.afterSendOperation(appPacket, false);
            log.error(String.format("%s.远程接口调用失败,异常信息:[%s].内容:[%s]", methodName, e.getMessage(), appPacket.getContext()));
        }
        // log
        packetHandler.afterSendOperation(appPacket, result.getDataResult());

        log.info(String.format("%s发送完成:结果:[%s--%s]***domainId:[%s].tempId:[%s].extparam:[%s].接收人:[%s-%s].发送内容:[%s].retryId:[%s]",
                methodName, result.getDataResult(), result.getMessage(), appPacket.getDomainId(), appPacket.getTemplateId(),
                appPacket.getExtParam(), appPacket.getRecvUserId(), appPacket.getDeviceToken(), appPacket.getContext(),
                appPacket.getDbRetryId()));

        return result;
    }

    @Override
    protected Tasks getTaskType() {
        return Tasks.FETCH_RETRY_QQ;
    }

    @Override
    protected String getQueueName() {
        return "qq推送处理队列";
    }

    @Override
    protected Tasks getFullTaskType() {
        return Tasks.FETCH_RETRY_QQ_FULL;
    }

    @Override
    protected String getFullQueueName() {
        return "qq全量推送处理队列";
    }

}
